package com.itmuch.cloud.fallback;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import com.netflix.hystrix.exception.HystrixTimeoutException;

@Component
public class MyFallbackProvider implements FallbackProvider{
 
	  //代码示例参考：
	  //http://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#hystrix-fallbacks-for-routes
	  @Override
	    public String getRoute() {
	        return "*";
	    }

	    @Override
	    public ClientHttpResponse fallbackResponse(final Throwable cause) {
	        if (cause instanceof HystrixTimeoutException) {
	            return response(HttpStatus.GATEWAY_TIMEOUT);
	        } else {
	            return fallbackResponse();
	        }
	    }

	    @Override
	    public ClientHttpResponse fallbackResponse() {
	    	//zuul 默认支持轮询的负载均衡策略，比如user:6900,user:6901
	    	//如果其中一台机器挂断会返回HttpStatus.INTERNAL_SERVER_ERROR 
	    	//过几秒zuul 将挂掉的服务 从列表中移除
	    	//如果服务列表中没有要访问的server，那么浏览器将报404错误，没有找到请求的地址
	    	
	    	//user集群部署存在一个问题：由于zuul是以轮询的方式实现负载均衡的，版本发布需要一个过程，可能会出现A用户访问旧版本 B用户访问新版本的情况，怎么解决？
	    	// nginx + zuul 
	    	//思路：1.先发布一个新服务到eureka，然后停掉所有旧服务，最后发布所有新服务
	    	//    2.部署两套环境，通过切流量访问其中一个环境
	    	
	    	
	    	//扼杀模式和本地前进 迁移现有应用程序或API时的常见模式是“扼杀”旧端点，用不同的实现慢慢替换它们。主要用于流量切换 
	        return response(HttpStatus.INTERNAL_SERVER_ERROR);
	    }

	    private ClientHttpResponse response(final HttpStatus status) {
	        return new ClientHttpResponse() {
	            @Override
	            public HttpStatus getStatusCode() throws IOException {
	                return status;
	            }

	            @Override
	            public int getRawStatusCode() throws IOException {
	                return status.value();
	            }

	            @Override
	            public String getStatusText() throws IOException {
	                return status.getReasonPhrase();
	            }

	            @Override
	            public void close() {
	            }

	            @Override
	            public InputStream getBody() throws IOException {
	                return new ByteArrayInputStream("fallback".getBytes());
	            }

	            @Override
	            public HttpHeaders getHeaders() {
	                HttpHeaders headers = new HttpHeaders();
	                headers.setContentType(MediaType.APPLICATION_JSON);
	                return headers;
	            }
	        };
	    }

	

}
